package com.fyp.ptma.controllers;

import java.io.BufferedReader;
import java.io.InputStream;
import java.io.StringReader;
import java.util.HashSet;
import java.util.List;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.Unmarshaller;

import org.apache.commons.io.IOUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.context.support.WebApplicationContextUtils;

import com.fyp.ptma.dao.service.iservice.IApplicationService;
import com.fyp.ptma.dao.service.iservice.IDefectService;
import com.fyp.ptma.dao.service.iservice.IDownloaderService;
import com.fyp.ptma.model.Application;
import com.fyp.ptma.model.Defect;
import com.fyp.ptma.model.Downloader;
import com.fyp.ptma.model.Installation;

/**
 * 
 * @author yahya
 * 
 */
@Controller
@RequestMapping(value = "/mobile")
public class MobileRequestsHandler extends AbstractController {

	@Autowired
	private IDownloaderService downloaderService;
	@Autowired
	private IDefectService defectService;
	@Autowired
	private IApplicationService appService;

	@RequestMapping(value = "/authenticate", method = RequestMethod.POST)
	public @ResponseBody
	Response autheticate(HttpServletRequest request,
			HttpServletResponse response) {
		Response responseXml = new Response();
		try {
			BufferedReader reader = request.getReader();
			StringBuilder xml = new StringBuilder(100);
			String line = null;
			while ((line = reader.readLine()) != null) {
				xml.append(line);
			}
			JAXBContext context = JAXBContext.newInstance(Downloader.class);

			Unmarshaller um = context.createUnmarshaller();
			Downloader downloader = (Downloader) um.unmarshal(new StringReader(
					xml.toString()));

			// Retrive device with device and email

			Downloader dbObj = null;

			if (downloader.getEmail() != null
					&& downloader.getUser().getEmail() != null) {
				dbObj = downloaderService
						.getDownloaderByEmailAndDeviceId(downloader);
			}
			if (dbObj == null && downloader.getDeviceId() != null) {
				dbObj = downloaderService.getDownloaderByDeviceId(downloader);
				if (dbObj != null) {
					downloaderService.saveOrUpdate(dbObj);
					responseXml.setStatusCode(Response.NOT_LOGGEDIN);
					return responseXml;

				} else {
					responseXml.setStatusCode(Response.NOT_REGISTERED);
					return responseXml;
				}
			}

			// both object are null this means user never invited and never
			// loggedin

			if (!dbObj.getInvitation().isAccepted()) {

				dbObj.getInvitation().setAccepted(true);

			}
			dbObj.setGoogleRegId(downloader.getGoogleRegId());
			dbObj.setDeviceOs(downloader.getDeviceOs());
			dbObj.setApplications(null);
			downloaderService.saveOrUpdate(dbObj);

			// downloaderService.saveOrUpdate(dbObj);
			responseXml.setStatusCode(Response.OK);
			responseXml.setResponseBody(dbObj);
			request.getSession().setAttribute("MobileUser", dbObj);
			request.getSession().setMaxInactiveInterval(36000);

		} catch (Exception e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
		}

		return responseXml;
	}

	@RequestMapping(value = "/applications", method = RequestMethod.POST)
	public @ResponseBody
	Response androidApks(HttpServletRequest request,
			HttpServletResponse response) {

		Response responseXml = new Response();
		responseXml.setStatusCode(Response.OK);

		Downloader downloader = (Downloader) request.getSession().getAttribute(
				"MobileUser");

		List<Application> apps = downloaderService
				.getAllApplications(downloader);
		downloader.setApplications(apps);
		responseXml.setResponseBody(downloader);

		return responseXml;
	}

	@RequestMapping(value = "/getApk", method = RequestMethod.POST)
	public @ResponseBody
	byte[] getApplication(HttpServletRequest request,
			HttpServletResponse response) {

		try {
			Downloader downloader = (Downloader) request.getSession()
					.getAttribute("MobileUser");
			if (downloader != null) {
				ApplicationContext applicationContext = WebApplicationContextUtils
						.getWebApplicationContext(request.getSession()
								.getServletContext());
				InputStream in = applicationContext.getResource(
						"/resources/images/2.apk").getInputStream();

				return IOUtils.toByteArray(in);
			}
		} catch (Exception e) {
			e.printStackTrace();

		}

		return null;
	}

	@RequestMapping(value = "/login", method = RequestMethod.POST)
	public @ResponseBody
	Response login(HttpServletRequest request, HttpServletResponse response) {
		Response responseXml = new Response();
		try {

			BufferedReader reader = request.getReader();
			StringBuilder xml = new StringBuilder(100);
			String line = null;
			while ((line = reader.readLine()) != null) {
				xml.append(line);
			}
			JAXBContext context = JAXBContext.newInstance(Downloader.class);

			Unmarshaller um = context.createUnmarshaller();
			Downloader downloader = (Downloader) um.unmarshal(new StringReader(
					xml.toString()));
			Downloader dbObj = downloaderService
					.getDownloaderByEmailAndDeviceId(downloader);

			dbObj.getInvitation().setAccepted(true);

			if (dbObj.getEmail() == null) {
				dbObj.setEmail(downloader.getEmail());
			}

			responseXml.setStatusCode(Response.OK);
			downloaderService.saveOrUpdate(dbObj);
			request.getSession().setAttribute("MobileUser", dbObj);
			request.getSession().setMaxInactiveInterval(36000);

		} catch (Exception e) {
			e.printStackTrace();
			responseXml.setStatusCode(Response.NOT_REGISTERED);
		}
		return responseXml;

	}

	@RequestMapping(value = "/submitDefect", method = RequestMethod.POST)
	public @ResponseBody
	Response submitDefect(HttpServletRequest request,
			HttpServletResponse response) {
		Response res = new Response();
		try {

			BufferedReader reader = request.getReader();
			StringBuilder xml = new StringBuilder(100);
			String line = null;
			while ((line = reader.readLine()) != null) {
				xml.append(line);
			}
			JAXBContext context = JAXBContext.newInstance(Defect.class);

			Unmarshaller um = context.createUnmarshaller();
			Defect defect = (Defect) um.unmarshal(new StringReader(xml
					.toString()));
			Downloader downloader = (Downloader) request.getSession()
					.getAttribute("MobileUser");

			defect.setAppVersion(appService.getApplicationVersionByPk(defect
					.getApplicationVersion().getVersionPk(), downloader
					.getUser().getEmail()));
			defectService.save(defect);
			res.setStatusCode(Response.OK);

		} catch (Exception e) {
			e.printStackTrace();
		}
		return res;
	}

	@RequestMapping(value = "/updateAppInstallStatus", method = RequestMethod.POST)
	public @ResponseBody
	Response updateInstallStatus(HttpServletRequest request,
			HttpServletResponse response) {

		Response res = new Response();

		try {

			Downloader downloader = (Downloader) request.getSession()
					.getAttribute("MobileUser");
			BufferedReader reader = request.getReader();
			StringBuilder xml = new StringBuilder(100);
			String line = null;
			while ((line = reader.readLine()) != null) {
				xml.append(line);
			}
			JAXBContext context = JAXBContext.newInstance(Installation.class);

			Unmarshaller um = context.createUnmarshaller();
			Installation notif = (Installation) um.unmarshal(new StringReader(
					xml.toString()));

			notif.setDownloader(downloader);
			notif.getInstallationPk().setDeviceId(downloader.getDeviceId());

			Installation ins = downloaderService.getInstallation(notif);
			if (ins == null)

				downloaderService.saveOrUpdate(notif);
			res.setStatusCode(Response.OK);
		} catch (Exception e) {
			e.printStackTrace();
		}
		return res;

	}
}
